#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <float.h>
#include <pthread.h>
#include <unistd.h>
#include "collectd.h"
#include "plugin.h"
#include "hisysevent_data.h"
#include "hisysevent_manager_c.h"
#include "commtraff_permission.h"


static HiSysEventWatchRule *watchList = NULL;
static FileEntry *entries = NULL;
static int entryCount = 0;
static pthread_t g_registerThread; // 添加线程变量

data_source_t g_dataSources[] = {
        {.name = "value", .type = DS_TYPE_GAUGE, .min = DBL_MIN, .max = DBL_MAX,},
};
static data_set_t g_testDS = {
        .ds = g_dataSources,
        .ds_num = sizeof(g_dataSources)/sizeof(data_source_t),
        .type = "hisyseventTest"
};

static void onEvent(HiSysEventRecordC record) {
    for (int i = 0; i < entryCount; ++i) {
        if (strcmp(record.eventName, entries[i].name) == 0) {
            for (int j = 0; j < entries[i].fieldCount; ++j) {
                // 只要有一个字段获取失败，就直接返回
                if (OH_HiSysEvent_GetParamUint64Value(&record, entries[i].field[j], &entries[i].fieldValues[j]) != 0) {
                    return;
                };
                DEBUG("eventName: %s, field %s: %" PRIu64"", record.eventName, entries[i].field[j], entries[i].fieldValues[j]);
            }

            value_list_t vl = VALUE_LIST_INIT;
            value_t val[MAX_FIELD_COUNT];
            char key[10] = {0};

            strncpy(vl.plugin, "hisysevent", sizeof(vl.plugin));
            strncpy(vl.type, entries[i].name, sizeof(vl.type));
            vl.meta = meta_data_create();
            meta_data_add_string(vl.meta, "domain", entries[i].domain);
            meta_data_add_string(vl.meta, "event", entries[i].name);

            for (int j = 0; j < entries[i].fieldCount; ++j) {
                snprintf(key, sizeof(key), "field%d", j);
                meta_data_add_string(vl.meta, key, entries[i].field[j]);
                val[j].gauge = entries[i].fieldValues[j];
            }
            vl.interval = DOUBLE_TO_CDTIME_T(1);
            vl.values = val;
            vl.values_len = entries[i].fieldCount;


            plugin_dispatch_values(&vl);
            meta_data_destroy(vl.meta);
        }
    }
}

static void onServiceDied() {
    INFO("service die.");
}

// 打印解析结果函数
void printEntries(const FileEntry *entries, int count) {
    INFO("Parsed %d entries:", count);
    INFO("%-20s %-32s %-15s %-10s %s", "Domain", "Event", "EventType", "FieldCount", "Fields");
    INFO("----------------------------------------------------------------------------------------------------");

    for (int i = 0; i < count; i++) {
        const char *eventTypeStr = (entries[i].eventType == HISYSEVENT_STATISTIC) ? "STATISTIC" : "BEHAVIOR";
        
        // 构建字段列表字符串
        char fieldsStr[512] = {0};
        if (entries[i].fieldCount > 0) {
            strncpy(fieldsStr, entries[i].field[0], sizeof(fieldsStr) - 1);
            for (int j = 1; j < entries[i].fieldCount && j < MAX_FIELD_COUNT; j++) {
                if (strlen(fieldsStr) + strlen(entries[i].field[j]) + 2 < sizeof(fieldsStr)) {
                    strcat(fieldsStr, ":");
                    strcat(fieldsStr, entries[i].field[j]);
                } else {
                    strcat(fieldsStr, ":...");
                    break;
                }
            }
        } else {
            strcpy(fieldsStr, "N/A");
        }
        
        INFO("%-20s %-32s %-15s %-10d %s", entries[i].domain, entries[i].name, 
             eventTypeStr, entries[i].fieldCount, fieldsStr);
    }
}

/**
 * @brief 解析hisysevent配置文件
 * 
 * 配置文件格式：域名,事件名,字段1:字段2:字段3[,事件类型]
 * 事件类型可选，支持STATISTIC和BEHAVIOR，默认为STATISTIC
 * 
 * 示例：
 * COMMONEVENT,PUBLISH,USER_ID:PID:UID,STATISTIC
 * BEHAVIOR_DOMAIN,BEHAVIOR_EVENT,FIELD1:FIELD2,BEHAVIOR  
 * DEFAULT_DOMAIN,DEFAULT_EVENT,FIELD1:FIELD2  (默认STATISTIC类型)
 */
static int parseConfigFile(const char* path) {
    FILE *fp = fopen(path, "r");
    if (fp == NULL) {
        ERROR("Error opening file.");
        return -1;
    }
    int count = 0;
    char line[MAX_LINE_LENGTH];
    while (fgets(line, sizeof(line), fp) != NULL && count < MAX_SUB_COUNT) {
        line[strcspn(line, "\n")] = '\0';
        
        // 跳过空行和注释行
        if (strlen(line) == 0 || line[0] == '#') {
            continue;
        }
        
        char *token = strtok(line, ",");
        if (token != NULL && strlen(token) > 0) {
            strncpy((entries)[count].domain, token, MAX_LENGTH_OF_EVENT_DOMAIN - 1);
            (entries)[count].domain[MAX_LENGTH_OF_EVENT_DOMAIN - 1] = '\0';
            
            token = strtok(NULL, ",");
            if (token != NULL && strlen(token) > 0) {
                strncpy((entries)[count].name, token, MAX_LENGTH_OF_EVENT_NAME - 1);
                (entries)[count].name[MAX_LENGTH_OF_EVENT_NAME - 1] = '\0';
                
                token = strtok(NULL, ",");
                if (token != NULL && strlen(token) > 0) {
                    // 先保存完整的字段+事件类型字符串
                    char fields_and_type[1024];
                    strncpy(fields_and_type, token, sizeof(fields_and_type) - 1);
                    fields_and_type[sizeof(fields_and_type) - 1] = '\0';
                    
                    // 继续读取下一个token，看是否有事件类型
                    char *next_token = strtok(NULL, ",");
                    
                    // 默认事件类型
                    (entries)[count].eventType = HISYSEVENT_STATISTIC;
                    
                    // 如果有下一个token，那就是事件类型
                    if (next_token != NULL && strlen(next_token) > 0) {
                        if (strcmp(next_token, "STATISTIC") == 0) {
                            (entries)[count].eventType = HISYSEVENT_STATISTIC;
                        } else if (strcmp(next_token, "BEHAVIOR") == 0) {
                            (entries)[count].eventType = HISYSEVENT_BEHAVIOR;
                        } else {
                            // 未知事件类型，默认为STATISTIC
                            (entries)[count].eventType = HISYSEVENT_STATISTIC;
                            INFO("Unknown event type '%s', using STATISTIC as default", next_token);
                        }
                        
                        // 字段字符串就是fields_and_type
                        // (不包含事件类型)
                    } else {
                        // 没有下一个token，检查字段字符串是否以事件类型结尾
                        char *last_colon = strrchr(fields_and_type, ':');
                        if (last_colon != NULL) {
                            char *potential_type = last_colon + 1;
                            if (strcmp(potential_type, "STATISTIC") == 0 || strcmp(potential_type, "BEHAVIOR") == 0) {
                                // 最后一个字段是事件类型
                                if (strcmp(potential_type, "BEHAVIOR") == 0) {
                                    (entries)[count].eventType = HISYSEVENT_BEHAVIOR;
                                } else {
                                    (entries)[count].eventType = HISYSEVENT_STATISTIC;
                                }
                                // 去掉最后的事件类型部分
                                *last_colon = '\0';
                            }
                        }
                    }
                    
                    // 解析字段
                    char *field_token = strtok(fields_and_type, ":");
                    int index = 0;
                    while (field_token != NULL && index < MAX_FIELD_COUNT) {
                        // 去除字段前后的空白字符
                        while (*field_token == ' ' || *field_token == '\t') field_token++;
                        if (strlen(field_token) > 0) {
                            strncpy((entries)[count].field[index], field_token, MAX_FIELD_LENGTH - 1);
                            (entries)[count].field[index][MAX_FIELD_LENGTH - 1] = '\0';
                            index++;
                        }
                        field_token = strtok(NULL, ":");
                    }
                    (entries)[count].fieldCount = index;
                    
                    // 只有当域名和事件名都非空时才计数这个条目
                    count++;
                } else {
                    // 没有字段，但域名和事件名存在，设置默认值
                    (entries)[count].field[0][0] = '\0';
                    (entries)[count].fieldCount = 0;
                    (entries)[count].eventType = HISYSEVENT_STATISTIC;
                    count++;
                }
            } else {
                ERROR("Invalid line format: missing event name - '%s'", line);
            }
        } else {
            ERROR("Invalid line format: missing domain - '%s'", line);
        }
    }
    fclose(fp);
    entryCount = count;
    printEntries(entries, entryCount);
    // register dataset
    for (int i = 0; i < entryCount; ++i) {
        data_set_t dsett;
        data_source_t dsrct[MAX_FIELD_COUNT];
        for (int j = 0; j < entries[i].fieldCount; ++j) {
            strncpy(dsrct[j].name, entries[i].field[j], MAX_FIELD_LENGTH);
            dsrct[j].type = DS_TYPE_GAUGE;
            dsrct[j].min = DBL_MIN;
            dsrct[j].max = DBL_MAX;
        }
        strncpy(dsett.type, entries[i].name, MAX_LENGTH_OF_EVENT_NAME);
        dsett.ds = dsrct;
        dsett.ds_num = entries[i].fieldCount;
        plugin_register_data_set(&dsett);
    }
    return 0;
}


static void* registerHisysevent(void* arg) {
    for (int i = 0; i < entryCount; ++i) {
        strncpy(watchList[i].domain, entries[i].domain, MAX_LENGTH_OF_EVENT_DOMAIN);
        strncpy(watchList[i].name, entries[i].name, MAX_LENGTH_OF_EVENT_NAME);
        // RuleType::WHOLE_WORD is 1
        watchList[i].ruleType = 1;
        // 使用配置文件中解析出的事件类型
        watchList[i].eventType = entries[i].eventType;
    }
    HiSysEventWatcher watcher = {
        .OnEvent = onEvent,
        .OnServiceDied = onServiceDied
    };
    int32_t retryCount = 0;
    int32_t ret = 0;
    AddPermission();
    while ((ret = OH_HiSysEvent_Add_Watcher(&watcher, watchList, entryCount)) != 0 && retryCount < 1000) {
        ERROR("add watcher failed time: %d, ret=%d", retryCount+1, ret);
        sleep(1); // 等待1秒后重试
        retryCount++;
    }
    INFO("add watcher final ret=%d.", ret);
    return NULL;
}

static int data_init(void) {
    watchList = (HiSysEventWatchRule*)malloc(sizeof(HiSysEventWatchRule) * MAX_SUB_COUNT);
    if (watchList == NULL) {
        ERROR("malloc memory failed.");
        return -1;
    }
    memset(watchList, 0, sizeof(HiSysEventWatchRule) * MAX_SUB_COUNT);
    entries = (FileEntry *)malloc(sizeof(FileEntry) * MAX_SUB_COUNT);
    if (entries == NULL) {
        ERROR("malloc memory failed.");
        if (watchList) {
            free(watchList);
            watchList = NULL;
        }
        return -1;
    }
    memset(entries, 0, sizeof(FileEntry) * MAX_SUB_COUNT);
    if (parseConfigFile(CONFIG_FILE_PATH) != 0) {
        ERROR("parse config failed. %s", CONFIG_FILE_PATH);
        if (watchList) {
            free(watchList);
            watchList = NULL;
        }
        if (entries) {
            free(entries);
            entries = NULL;
        }
        return -1;
    }
    return 0;
}

static int hisysevent_init(void) {
    // 创建独立线程来执行注册操作
    int result = pthread_create(&g_registerThread, NULL, registerHisysevent, NULL);
    if (result != 0) {
        ERROR("Failed to create register thread: %d", result);
        return -1;
    }

    pthread_detach(g_registerThread);

    return 0;
}

static int hisysevent_config(oconfig_item_t *ci) {
    (void)ci;
    return 0;
}


void module_register(void) {
    if (data_init() != 0) {
        ERROR("init data failed");
        return;
    }
    plugin_register_data_set(&g_testDS);
    plugin_register_init("hisysevent", hisysevent_init);
    plugin_register_complex_config("hisysevent", hisysevent_config);
} /* void module_register */
